﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Walson.Windows.Forms
{
    public partial class DotLedDisplay : Control
    {
        private Bitmap _DarkPointBmp;
        private Bitmap _LightPointBmp;
        private Bitmap _StringBmp;
        private Bitmap _GraphicModeBuffer;
        
        private Timer _AnimationTimer;
        //private Timer _RefreshTimer;
        private SolidBrush _DarkPointBrush;
        private SolidBrush _LightPointBrush;
        private Size _StringSize;
        private bool _Ready = false;

        private string _Text = "Welcome";

        

        /// <summary>
        /// 控件的工作模式
        /// </summary>
        public enum Modes
        {
            /// <summary>
            /// 文本模式
            /// </summary>
            TextMode,
            /// <summary>
            /// 绘图模式
            /// </summary>
            GraphicMode
        }

        private Modes _Mode=Modes.TextMode;
        /// <summary>
        /// 当前模式
        /// </summary>
        public Modes Mode
        {
            get
            {
                return _Mode;
            }
            set
            {
                _Mode = value;
                if(_Mode==Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                }
                else
                {
                    DrawString();
                    this.Invalidate();
                }
            }
        }


        /// <summary>
        /// 要显示的文本
        /// </summary>
        public override string Text
        {
            get
            {
                return _Text;
            }
            set
            {
                _Text = value;

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }

                DrawString();
                this.Invalidate();
            }
        }

        private int _RowCount = 16;
        /// <summary>
        /// 行数
        /// </summary>
        public int RowCount
        {
            get
            {
                return _RowCount;
            }
            set
            {
                _RowCount = value;
                this.Size = new Size(this.ColCount * (_DotSize + _Gap), this.RowCount * (_DotSize + _Gap));

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }

                DrawString();
                this.Invalidate();
            }

        }

        private int _ColCount = 128;
        /// <summary>
        /// 列数
        /// </summary>
        public int ColCount
        {
            get
            {
                return _ColCount;
            }
            set
            {
                _ColCount = value;
                this.Size = new Size(this.ColCount * (_DotSize + _Gap), this.RowCount * (_DotSize + _Gap));

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }

                DrawString();
                this.Invalidate();
            }
        }

        private int _Gap = 1;
        /// <summary>
        /// 点距
        /// </summary>
        public int Gap
        {
            get
            {
                return _Gap;
            }
            set
            {
                _Gap = value;
                this.Size = new Size(this.ColCount * (_DotSize + _Gap), this.RowCount * (_DotSize + _Gap));

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }


                DrawString();
                this.Invalidate();
            }
        }

        private int _DotSize = 2;
        /// <summary>
        /// 点的尺寸
        /// </summary>
        public int DotSize
        {
            get
            {
                return _DotSize;
            }
            set
            {
                if (value > 100)
                    return;
                _DotSize = value;
                this.Size = new Size(this.ColCount * (_DotSize + _Gap), this.RowCount * (_DotSize + _Gap));

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }


                DrawString();
                this.Invalidate();
            }
        }

        private bool _Animation = false;
        /// <summary>
        /// 是否动画
        /// </summary>
        public bool Animation
        {
            get
            {
                return _Animation;
            }
            set
            {
                _Animation = value;
                if (_Animation)
                {
                    _AnimationTimer.Enabled = true;
                }
                else
                {
                    _AnimationTimer.Enabled = false;
                }
            }
        }

        private int _OffsetY = 0;
        /// <summary>
        /// Y 方向偏移
        /// </summary>
        public int OffsetY
        {
            get
            {
                return _OffsetY;
            }
            set
            {
//                 if (value < 0)
//                     return;
                _OffsetY = value;
                
                this.Invalidate();
            }
        }

        private int _OffsetX = 0;
        /// <summary>
        /// X 方向偏移
        /// </summary>
        public int OffsetX
        {
            get
            {
                return _OffsetX;
            }
            set
            {
//                 if (value < 0)
//                     return;
                _OffsetX = value;
                //DrawString();
                this.Invalidate();
            }
        }

        private Color _DarkPointColor = Color.Maroon;
        /// <summary>
        /// 未点亮点的颜色
        /// </summary>
        public Color DarkPointColor
        {
            get
            {
                return _DarkPointColor;
            }
            set
            {
                _DarkPointColor = value;
                _DarkPointBrush.Dispose();
                _DarkPointBrush = null;
                _DarkPointBrush = new SolidBrush(value);

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }

                DrawString();
                this.Invalidate();
            }
        }

        private Color _LightPointColor = Color.Red;
        /// <summary>
        /// 点亮点的颜色
        /// </summary>
        public Color LightPointColor
        {
            get
            {
                return _LightPointColor;
            }
            set
            {
                _LightPointColor = value;
                _LightPointBrush.Dispose();
                _LightPointBrush = null;
                _LightPointBrush = new SolidBrush(value);

                if (this._Mode == Modes.GraphicMode)
                {
                    Clear();
                    this.Invalidate();
                    return;
                }

                DrawString();
                this.Invalidate();
            }
        }

        /// <summary>
        /// 背景色
        /// </summary>
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
                this.Invalidate();
            }
        }

        /// <summary>
        /// 动画时间间隔
        /// </summary>
        public int AnimationInterval
        {
            get
            {
                return _AnimationTimer.Interval;
            }
            set
            {
                _AnimationTimer.Interval = value;
            }
        }

        public SizeF CurrentTextSize
        {
            get;
            private set;
        }

        private void ConvertBitmapToDot(Bitmap bmp)
        {
            int x = 0;
            int y = 0;
            int w = _DotSize;
            int h = _DotSize;
            _DarkPointBmp = new Bitmap(this.Width, this.Height);
            using (Graphics g = Graphics.FromImage(_DarkPointBmp))
            {
                for (int i = 0; i < _RowCount; i++)
                {
                    for (int j = 0; j < _ColCount; j++)
                    {
                        g.FillEllipse(_DarkPointBrush, x, y, w, h);
                        x += (_DotSize + _Gap);
                    }
                    x = 0;
                    y += (_DotSize + _Gap);
                }
            }

            x = 0;
            y = 0;
            w = _DotSize;
            h = _DotSize;
            _LightPointBmp = new Bitmap(bmp.Width * (_DotSize + _Gap), bmp.Height * (_DotSize + _Gap));
            using (Graphics g = Graphics.FromImage(_LightPointBmp))
            {
                for (int i = 0; i < bmp.Height; i++)
                {
                    for (int j = 0; j < bmp.Width; j++)
                    {
                        //g.FillRectangle(Brushes.Maroon, x , y, w, h);
                        if (i < bmp.Height && j < bmp.Width)
                        {
                            if (bmp.GetPixel(j, i).A != 0)
                            {
                                g.FillEllipse(_LightPointBrush, x, y, w, h);
                            }
                        }
                        x += (_DotSize + _Gap);
                    }
                    x = 0;
                    y += (_DotSize + _Gap);
                }
            }
        }

        private void DrawString()
        {

            //SizeF size;
            using (Bitmap bmp = new Bitmap(1,1))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    CurrentTextSize = g.MeasureString(this.Text, this.Font);
                }
            }


            if (_StringBmp==null || _StringBmp.Width != Math.Ceiling(CurrentTextSize.Width) || _StringBmp.Height != Math.Ceiling(CurrentTextSize.Height))
                _StringBmp = new Bitmap((int)Math.Ceiling(CurrentTextSize.Width), (int)Math.Ceiling(CurrentTextSize.Height));

            //using (Bitmap _StringBmp = new Bitmap((int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height)))
            {
                using (Graphics g = Graphics.FromImage(_StringBmp))
                {
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.Clear(Color.Transparent);
                    g.DrawString(this.Text, this.Font, Brushes.Black, 0, 0);
                }
                _StringSize = _StringBmp.Size;

                ConvertBitmapToDot(_StringBmp);
            }
        }

        /// <summary>
        /// 绘制一个像素。仅在 GraphicMode 下有效。
        /// </summary>
        /// <param name="x">像素的 X 坐标</param>
        /// <param name="y">像素的 Y 坐标</param>
        /// <param name="color">像素的颜色，为 true 时绘制前景色，为 false 时绘制背景色</param>
        public void DrawPixel(int x,int y,bool color)
        {
            if (_Mode == Modes.TextMode)
                return;

            if(_GraphicModeBuffer==null)
            {
                _GraphicModeBuffer = new Bitmap(_ColCount, _RowCount);
            }

            if (color)
                _GraphicModeBuffer.SetPixel(x, y, this._LightPointColor);
            else
                _GraphicModeBuffer.SetPixel(x, y, this._DarkPointColor);

            ConvertBitmapToDot(_GraphicModeBuffer);
        }

        /// <summary>
        /// 绘图。图像背景色必须是透明色。
        /// </summary>
        /// <param name="x">暂未使用</param>
        /// <param name="y">暂未使用</param>
        /// <param name="bmp">要绘制的图像</param>
        public void DrawImage(int x,int y,Bitmap bmp)
        {
//             using(Graphics g=Graphics.FromImage(bmp))
//             {
//                 g.DrawString("Test!", new Font("宋体", 9), Brushes.White, 0, 0);
//             }

            ConvertBitmapToDot(bmp);

            this.Invalidate();
        }

        /// <summary>
        /// 清除图像。仅在 GraphicMode 下有效。
        /// </summary>
        public void Clear()
        {
            if (_Mode == Modes.TextMode)
                return;

            if (_GraphicModeBuffer == null)
            {
                _GraphicModeBuffer = new Bitmap(_ColCount, _RowCount);
            }
            using(Graphics g=Graphics.FromImage(_GraphicModeBuffer))
            {
                g.Clear(Color.Transparent);
            }

            ConvertBitmapToDot(_GraphicModeBuffer);
        }

        /// <summary>
        /// 刷新图像
        /// </summary>
        public void RefreshGraphic()
        {
            this.Invalidate();
        }

        /// <summary>
        /// 点阵式 LED 显示屏
        /// </summary>
        public DotLedDisplay()
        {
            InitializeComponent();
            this.DoubleBuffered = true;

            this.Size = new Size(this.ColCount * (_DotSize + _Gap), this.RowCount * (_DotSize + _Gap));

            this.BackColor = Color.Black;
            _LightPointBrush = new SolidBrush(_LightPointColor);
            _DarkPointBrush = new SolidBrush(_DarkPointColor);
            DrawString();

            _OffsetX = 0;

            _AnimationTimer = new Timer();
            _AnimationTimer.Enabled = _Animation;
            _AnimationTimer.Interval = 100;
            _AnimationTimer.Tick += delegate
            {
                if (_Animation && _Mode==Modes.TextMode)
                {
                    _OffsetX--;
                    if (_OffsetX == 0 - _StringSize.Width)
                        _OffsetX = _ColCount;
                    this.Invalidate();
                }
                
            };

            this.FontChanged += delegate
            {
                DrawString();
                this.Invalidate();
            };

            this.SizeChanged += delegate
            {
                this.Size = new Size(this.ColCount * (_DotSize + _Gap), this.RowCount * (_DotSize + _Gap));
            };

            _Ready = true;
        }

//         protected override void OnPaint(PaintEventArgs e)
//         {
//             if (_Ready == false)
//                 return;
// 
//             using (Bitmap bmp = new Bitmap(this.Width, this.Height))
//             {
//                 using (Graphics g = Graphics.FromImage(bmp))
//                 {
//                     g.Clear(this.BackColor);
//                     using (Bitmap bmp2 = new Bitmap(_ColCount, _RowCount))
//                     {
//                         using (Graphics g2 = Graphics.FromImage(bmp2))
//                         {
//                             g2.SmoothingMode = SmoothingMode.AntiAlias;
// 
//                             g2.TranslateTransform(_OffsetX, _OffsetY);
//                             g2.DrawImage(_StringBmp, 0, 0);
//                             g2.ResetTransform();
//                         }
// 
//                         //g.DrawImage(bmp2, 0, 0);
//                         int x = 0;
//                         int y = 0;
//                         int w = _DotSize;
//                         int h = _DotSize;
// 
//                         for (int i = 0; i < _RowCount; i++)
//                         {
//                             for (int j = 0; j < _ColCount; j++)
//                             {
//                                 g.FillEllipse(_DarkPointBrush, x, y, w, h);
//                                 //g.FillRectangle(Brushes.Maroon, x , y, w, h);
//                                 if (i < bmp2.Height && j < bmp2.Width)
//                                 {
//                                     if (bmp2.GetPixel(j, i).A != 0)
//                                     {
//                                         //g.FillRectangle(Brushes.Red, x, y, w, h);
//                                         g.FillEllipse(_LightPointBrush, x, y, w, h);
//                                     }
//                                 }
//                                 x += (_DotSize + _Gap);
//                             }
//                             x = 0;
//                             y += (_DotSize + _Gap);
//                         }
// // 
//                     }
// 
//                    
//                     
//                     //g.DrawImage(_StringBmp, 0, 0);
//                 }
//                 e.Graphics.DrawImage(bmp, 0, 0);
//             }
//             
//             base.OnPaint(e);
//         }

        /// <summary>
        /// 绘图
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (_Ready == false)
                return;

            using (Bitmap bmp = new Bitmap(this.Width, this.Height))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    if (_Mode == Modes.TextMode)
                    {
                        g.Clear(this.BackColor);
                        g.DrawImage(_DarkPointBmp, 0, 0);
                        g.DrawImage(_LightPointBmp, (_DotSize + _Gap) * _OffsetX, (_DotSize + _Gap) * _OffsetY);
                        //g.DrawImage(_LightPointBmp, 0, 0);
                    }
                    else
                    {
                        g.Clear(this.BackColor);
                        g.DrawImage(_DarkPointBmp, 0, 0);
                        g.DrawImage(_LightPointBmp, 0, 0);
                    }
                }
                e.Graphics.DrawImage(bmp, 0, 0);
            }

            base.OnPaint(e);
        }
    }
}
